package com.restfinder.user.model;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;

import org.hibernate.annotations.ForeignKey;

import com.restfinder.comment.model.Comment;
import com.restfinder.model.IEntity;
import com.restfinder.restaurant.model.Restaurant;

import lombok.Getter;
import lombok.Setter;

@Entity
@Table(name="users")
public class User implements IEntity {

	private static final long serialVersionUID = 1L;
	
	// -- Fields --
	
	@Id
	@GeneratedValue
	@Getter @Setter
	private long id;
	
	@Getter @Setter
	private String name;
	
	@Getter @Setter
	private String surname;
	
	@Column(unique=true, nullable=false)
	@Getter @Setter
	private String username;
	
	@Getter @Setter
	private String email;
	
	@Getter @Setter
	private String password;
	
	@Column(name="avatar_src")
	@Getter @Setter
	private String avatarSrc;
	
	@ManyToMany
	@JoinTable(name="rel_users_roles",
	 joinColumns=@JoinColumn(name="user_id"),
	 inverseJoinColumns=@JoinColumn(name="role_id")
	)
	@ForeignKey(name="rel_users_roles_fk_user_id")
	@Getter @Setter
	private List<Role> roles = new ArrayList<Role>();
	
	@Getter @Setter
	private boolean enabled;
	
	@OneToOne(fetch=FetchType.LAZY, mappedBy="owner", targetEntity=Restaurant.class)
	@JoinColumn(name="restaurant_id")
	@ForeignKey(name="users_fkey_restaurant_id")
	@Getter @Setter
	private Restaurant restaurant;
	
	@OneToMany(cascade=CascadeType.ALL, targetEntity=Comment.class, mappedBy="user")
	@Getter @Setter
	private List<Comment> comments;
	
	// -- Methods --
	/**
	 * Adds role to user, if user doesn't have one.
	 * @param role Role to add
	 */
	public void add(Role role){
		if(!roles.contains(role)){
			roles.add(role);
		}		
	}
	
	/**
	 * Checks if user has role with the given code
	 * @param roleCode code of {@link Role#getCode()}
	 * @return
	 */
	public boolean hasRole(String roleCode){
		for(Role role : roles){
			if(role.getCode().equalsIgnoreCase(roleCode)){
				return true;
			}
		}
		return false;
	}
	
	/**
	 * Checks if user has role 
	 * @param role {@link Role}
	 * @return
	 */
	public boolean hasRole(Role role){
		return roles.contains(role);
	}
	
	/**
	 * Checks if String regex expression of user's email is valid
	 * @return
	 */
	public boolean hasValidEmail(){
		return true;	//TODO 
	}

	@Override
	public boolean equals(Object obj) {
		if(this == obj) return true;
		if ((obj == null) || !(obj instanceof User)) {
			return false;
		}
		User objUser = (User) obj;
		return objUser.getId() == this.id;		
	}

	@Override
	public String toString() {
		return "User.id="+this.id;
	}
	
	/*@ManyToMany
	@JoinTable(name="rel_users_friends",
	 joinColumns=@JoinColumn(name="user_id"),
	 inverseJoinColumns=@JoinColumn(name="friend_id")
	)
	@Getter @Setter
	private List<User> friends;
	@ManyToMany
	@JoinTable(name="rel_users_friends",
	 joinColumns=@JoinColumn(name="friend_id"),
	 inverseJoinColumns=@JoinColumn(name="user_id")
	)
	@Getter @Setter
	private List<User> friendOf;
	@ManyToMany
	@JoinTable(name="rel_users_restaurants_own",
	 joinColumns=@JoinColumn(name="user_id"),
	 inverseJoinColumns=@JoinColumn(name="restaurant_id")
	)
	@Getter @Setter
	private List<Restaurant> ownedRestaurants;*/
}
